package com.zbkj.admin.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zbkj.admin.filter.TokenComponent;
import com.zbkj.admin.model.req.AdminBindBankcardReq;
import com.zbkj.admin.model.req.UnbindMerchantReq;
import com.zbkj.admin.model.req.UpdateBindMerchantReq;
import com.zbkj.admin.model.req.UpdateSpreaderReq;
import com.zbkj.admin.service.AdminUserV2Service;
import com.zbkj.dal.base.enums.*;
import com.zbkj.dal.common.exception.CrmebException;
import com.zbkj.dal.common.utils.CrmebDateUtil;
import com.zbkj.dal.common.utils.JsonUtil;
import com.zbkj.dal.dao.*;
import com.zbkj.dal.entity.merchant.Merchant;
import com.zbkj.dal.entity.merchant.MerchantEmployee;
import com.zbkj.dal.entity.user.*;
import com.zbkj.service.manager.MerchantManager;
import com.zbkj.service.manager.UserManager;
import com.zbkj.service.model.front.req.user.UpdateUserIdentityReq;
import com.zbkj.service.model.front.req.user.UserLogoffReq;
import com.zbkj.service.model.front.req.user.UserUpdateAuthorityReq;
import com.zbkj.service.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.Objects;

@Service
public class AdminUserV2ServiceImpl implements AdminUserV2Service {

    @Resource
    private UserDao userDao;

    @Resource
    private UserBankDao userBankDao;

    @Resource
    private MerchantDao merchantDao;

    @Resource
    private EmployeeDao employeeDao;

    @Resource
    private UserManager userManager;

    @Resource
    private UserService userService;

    @Resource
    private TokenComponent tokenComponent;

    @Resource
    private MerchantManager merchantManager;

    @Resource
    private EmployeeAccountDao employeeAccountDao;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private MerchantEmployeeDao merchantEmployeeDao;

    @Resource
    private UserActivityRecordDao userActivityRecordDao;

    /**
     * 如果用户之前是会员，修改为店长
     * 查询当前店铺是否有生效的店长
     * 修改用户信息
     * 修改店铺信息
     * 关联员工信息，创建员工账号（如果没有）
     * 添加店铺员工
     * <p>
     * 如果之前是动态店长，修改为店长
     * 修改用户信息
     * 修改店铺信息
     * 修改店铺员工信息
     * <p>
     * 如果用户之前是会员，修改为动态店长
     * 修改用户信息
     * 关联员工信息，创建员工账号（如果没有）
     * 添加店铺员工
     * <p>
     * 如果用户之前是店长，修改为动态店长
     * 修改用户信息
     * 修改店铺信息
     * 关联员工信息，创建员工账号（如果没有）
     * 修改店铺员工信息
     * <p>
     * 如果用户之前是店长，修改为会员
     * 修改用户信息
     * 修改店铺信息
     * 禁用店铺员工
     * <p>
     * 如果之前是动态店长，修改为会员
     * 修改用户信息
     * 禁用店铺员工
     */
    @Override
    public void updateUserIdentity(UpdateUserIdentityReq req) {
        Integer userId = req.getUserId();
        String identity = req.getIdentity();

        // 查询用户员工信息,从用户侧发起身份变更时，需要先确认当前用户已指定为员工
        LambdaQueryWrapper<EmployeeAccount> employeeAccountWrapper = new LambdaQueryWrapper<>();
        employeeAccountWrapper.eq(EmployeeAccount::getAccountId, userId);
        employeeAccountWrapper.eq(EmployeeAccount::getAccountType, AccountTypeEnums.FRONT.name());
        employeeAccountWrapper.eq(EmployeeAccount::getDeleted, BooleanEnums.FALSE.getCode());
        EmployeeAccount employeeAccount = employeeAccountDao.selectOne(employeeAccountWrapper);
        if (Objects.isNull(employeeAccount)) {
            throw new CrmebException("当前用户未指定为员工");
        }
        String employeeNo = employeeAccount.getEmployeeNo();
        this.updateIdentity(employeeNo, userId, identity, null);
    }

    @Override
    public void updateIdentity(@NotNull String employeeNo, @NotNull Integer userId, @NotNull String identity, Integer merId) {
        transactionTemplate.execute(e -> {
            User user = userManager.findByUserId(userId);
            Integer merchantId = Objects.isNull(merId) ? user.getSpreadMerchantId() : merId;
            LambdaUpdateWrapper<User> userUpdateWrapper = new LambdaUpdateWrapper<>();
            userUpdateWrapper.set(User::getSpreadMerchantId, merchantId);
            if (StringUtils.equals(user.getIdentity(), identity)) {
                return true;
            }

            if (StringUtils.equals(identity, UserIdentityEnums.STORE_MANAGER.getCode()) || StringUtils.equals(identity, UserIdentityEnums.DYNAMIC_STORE_MANAGER.getCode())) {
                if (Objects.isNull(merchantId)) {
                    throw new CrmebException("店铺id不能为空");
                }
                Merchant merchant = merchantManager.findByMerchantId(merchantId);

                LambdaQueryWrapper<Employee> employeeWrapper = new LambdaQueryWrapper<>();
                employeeWrapper.eq(Employee::getEmployeeNo, employeeNo);
                employeeWrapper.eq(Employee::getStatus, EmployeeStatusEnum.ENABLE.getCode());
                employeeWrapper.eq(Employee::getDeleted, BooleanEnums.FALSE.getCode());
                Employee employee = employeeDao.selectOne(employeeWrapper);
                if (Objects.isNull(employee)) {
                    throw new CrmebException("员工信息异常，请确认后重试");
                }

                // 如果是会员或者动态店长修改为店长，检查当前店铺是否已经有店长，且店长没有推荐人
                if (StringUtils.equals(identity, UserIdentityEnums.STORE_MANAGER.getCode())) {
                    userUpdateWrapper.eq(User::getSpreadUid, 0);
                    if (Objects.nonNull(merchant.getManagerUid())) {
                        throw new CrmebException("当前店铺已经存在店长，请确认后重新提交");
                    }
                    LambdaUpdateWrapper<Merchant> merchantUpdateWrapper = new LambdaUpdateWrapper<>();
                    merchantUpdateWrapper.set(Merchant::getManagerUid, userId);
                    merchantUpdateWrapper.set(Merchant::getUpdateTime, CrmebDateUtil.nowDateTime());
                    merchantUpdateWrapper.eq(Merchant::getId, merchant.getId());
                    merchantDao.update(null, merchantUpdateWrapper);
                }

                // 如果是店长改为动态店长，修改店铺信息
                if (StringUtils.equals(user.getIdentity(), UserIdentityEnums.STORE_MANAGER.getCode()) ||
                        StringUtils.equals(identity, UserIdentityEnums.DYNAMIC_STORE_MANAGER.getCode())) {
                    userUpdateWrapper.eq(User::getSpreadUid, merchant.getManagerUid());
                    LambdaUpdateWrapper<Merchant> merchantUpdateWrapper = new LambdaUpdateWrapper<>();
                    merchantUpdateWrapper.set(Merchant::getManagerUid, null);
                    merchantUpdateWrapper.set(Merchant::getUpdateTime, CrmebDateUtil.nowDateTime());
                    merchantUpdateWrapper.eq(Merchant::getId, merchant.getId());
                    merchantDao.update(null, merchantUpdateWrapper);
                }

                MerchantEmployee merchantEmployee = merchantManager.findMerchantEmployee(employeeNo);
                if (Objects.isNull(merchantEmployee)) {
                    merchantEmployee = new MerchantEmployee();
                    merchantEmployee.setEmployeeNo(employeeNo);
                    merchantEmployee.setMerchantId(merchantId);
                    merchantEmployee.setUserId(userId);
                    merchantEmployee.setIdentity(identity);
                    merchantEmployee.setCreateTime(LocalDateTime.now());
                    merchantEmployee.setUpdateTime(LocalDateTime.now());
                    merchantEmployee.setDeleted(BooleanEnums.FALSE.getCode());
                    merchantEmployeeDao.insert(merchantEmployee);
                } else {
                    LambdaUpdateWrapper<MerchantEmployee> updateWrapper = new LambdaUpdateWrapper<>();
                    if (!Objects.equals(merchantEmployee.getMerchantId(), merchantId)) {
                        // 如果指定店铺和已存在的店铺不相同，作废原有身份，创建新身份
                        updateWrapper.set(MerchantEmployee::getEnable, BooleanEnums.FALSE.getCode());
                        updateWrapper.set(MerchantEmployee::getUpdateTime, LocalDateTime.now());
                        updateWrapper.eq(MerchantEmployee::getId, merchantEmployee.getId());
                        merchantEmployeeDao.update(null, updateWrapper);

                        MerchantEmployee newMerchantEmployee = new MerchantEmployee();
                        newMerchantEmployee.setEmployeeNo(merchantEmployee.getEmployeeNo());
                        newMerchantEmployee.setMerchantId(merchantId);
                        newMerchantEmployee.setUserId(merchantEmployee.getUserId());
                        newMerchantEmployee.setIdentity(merchantEmployee.getIdentity());
                        newMerchantEmployee.setEnable(BooleanEnums.TRUE.getCode());
                        newMerchantEmployee.setCreateTime(LocalDateTime.now());
                        newMerchantEmployee.setUpdateTime(LocalDateTime.now());
                        newMerchantEmployee.setDeleted(BooleanEnums.FALSE.getCode());
                        merchantEmployeeDao.insert(newMerchantEmployee);
                    } else {
                        // 如果指定店铺和已存在的店铺相同，则修改员工身份
                        updateWrapper.set(MerchantEmployee::getIdentity, identity);
                        updateWrapper.set(MerchantEmployee::getUpdateTime, LocalDateTime.now());
                        updateWrapper.eq(MerchantEmployee::getId, merchantEmployee.getId());
                        merchantEmployeeDao.update(null, updateWrapper);
                    }
                }
            } else if (StringUtils.equals(identity, UserIdentityEnums.MEMBER.getCode())) {
                // 查询店铺员工信息
                LambdaQueryWrapper<MerchantEmployee> merchantEmployeeWrapper = new LambdaQueryWrapper<>();
                merchantEmployeeWrapper.eq(MerchantEmployee::getUserId, userId);
                merchantEmployeeWrapper.eq(MerchantEmployee::getMerchantId, merchantId);
                merchantEmployeeWrapper.eq(MerchantEmployee::getEnable, BooleanEnums.TRUE.getCode());
                merchantEmployeeWrapper.eq(MerchantEmployee::getDeleted, BooleanEnums.FALSE.getCode());
                MerchantEmployee merchantEmployee = merchantEmployeeDao.selectOne(merchantEmployeeWrapper);

                if (Objects.nonNull(merchantEmployee)) {
                    // 店铺员工信息禁用
                    LambdaUpdateWrapper<MerchantEmployee> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.set(MerchantEmployee::getEnable, BooleanEnums.FALSE.getCode());
                    updateWrapper.set(MerchantEmployee::getUpdateTime, LocalDateTime.now());
                    updateWrapper.eq(MerchantEmployee::getId, merchantEmployee.getId());
                    merchantEmployeeDao.update(null, updateWrapper);
                }

                // 如果是店长改为会员，修改店铺信息
                if (StringUtils.equals(user.getIdentity(), UserIdentityEnums.STORE_MANAGER.getCode())) {
                    Merchant merchant = merchantManager.findByMerchantId(merchantEmployee.getMerchantId());
                    LambdaUpdateWrapper<Merchant> merchantUpdateWrapper = new LambdaUpdateWrapper<>();
                    merchantUpdateWrapper.set(Merchant::getManagerUid, null);
                    merchantUpdateWrapper.set(Merchant::getUpdateTime, CrmebDateUtil.nowDateTime());
                    merchantUpdateWrapper.eq(Merchant::getId, merchant.getId());
                    merchantDao.update(null, merchantUpdateWrapper);
                }
                merchantManager.disableMerchantEmployee(employeeNo);
            } else {
                throw new CrmebException("未知用户身份");
            }

            userUpdateWrapper.set(User::getIdentity, identity);
            userUpdateWrapper.set(User::getUpdateTime, LocalDateTime.now());
            userUpdateWrapper.eq(User::getId, user.getId());
            userDao.update(null, userUpdateWrapper);
            return true;
        });
    }


    @Override
    public void updateShareProfit(UserUpdateAuthorityReq req) {
        userManager.updateShareProfit(req.getUserId(), req.getEnable());

        UserActivityRecord userActivityRecord = new UserActivityRecord();
        userActivityRecord.setUserCode(String.valueOf(req.getUserId()));
        userActivityRecord.setActivityType(UserActivityTypeEnums.OPERATE_SHARE_PROFIT.getCode());
        userActivityRecord.setBizData(JsonUtil.toJSONString(req));
        userActivityRecord.setActivityDigest(String.format("%s用户%s分润权限-%s", BooleanEnums.isTrue(req.getEnable()) ? "启用" : "禁用", req.getUserId(), req.getRemark()));
        userActivityRecord.setCreateTime(LocalDateTime.now());
        userActivityRecord.setUpdateTime(LocalDateTime.now());
        userActivityRecord.setDeleted(BooleanEnums.FALSE.getCode());
        userActivityRecordDao.insert(userActivityRecord);
    }

    @Override
    public void userBlacklist(UserUpdateAuthorityReq req) {
        User user = userManager.findByUserId(req.getUserId());
        user.setUpdateTime(CrmebDateUtil.nowDateTime());
        user.setStatus(BooleanEnums.isTrue(req.getEnable()));
        userDao.updateById(user);

        UserActivityRecord userActivityRecord = new UserActivityRecord();
        userActivityRecord.setUserCode(String.valueOf(req.getUserId()));
        userActivityRecord.setActivityType(UserActivityTypeEnums.USER_DISABLE.getCode());
        userActivityRecord.setBizData(JsonUtil.toJSONString(req));
        userActivityRecord.setActivityDigest(String.format("拉黑用户%s-%s", req.getUserId(), req.getRemark()));
        userActivityRecord.setCreateTime(LocalDateTime.now());
        userActivityRecord.setUpdateTime(LocalDateTime.now());
        userActivityRecord.setDeleted(BooleanEnums.FALSE.getCode());
        userActivityRecordDao.insert(userActivityRecord);
    }

    @Override
    public void logoff(UserLogoffReq req) {
        User user = userManager.findByUserId(req.getUserId());
        String operator = tokenComponent.adminName();
        userService.logoff(user, String.format("管理员%s注销：%s", operator, req.getRemark()));
    }

    @Override
    public void updateBindBank(AdminBindBankcardReq req) {
        Integer userId = req.getUserId();
        UserBank userBank = userManager.userBankcard(userId);

        // 已存在银行卡先解绑，不存在直接添加
        if (Objects.nonNull(userBank)) {
            userManager.unbindBankcard(userId, userBank.getBankcardNo());
        }

        userManager.bindUserBankcard(userId, req.getAccountName(), req.getBankCode(), req.getBankcardNo());

    }

    @Override
    public void unbindMerchant(UnbindMerchantReq req) {
        User user = userManager.findByUserId(req.getUserId());
        if (Objects.isNull(user.getSpreadMerchantId())) {
            throw new CrmebException("该用户未绑定店铺");
        }
        if (!StringUtils.equals(user.getIdentity(), UserIdentityEnums.MEMBER.getCode())) {
            throw new CrmebException("请先解除用户身份，再解绑店铺");
        }
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(User::getSpreadMerchantId, null);
        updateWrapper.set(User::getUpdateTime, CrmebDateUtil.nowDateTime());
        updateWrapper.eq(User::getId, req.getUserId());
        userDao.update(null, updateWrapper);
    }

    /**
     * 修改推荐店铺
     * 同时修改推荐人，推荐人为店铺店长
     */
    @Override
    public void updateBindMerchant(UpdateBindMerchantReq req) {
        User user = userManager.findByUserId(req.getUserId());
        if (Objects.equals(req.getNewMerchantId(), user.getSpreadMerchantId())) {
            throw new CrmebException("换绑店铺与当前店铺相同");
        }

        // 查询店铺店长
        Merchant merchant = merchantDao.selectById(req.getNewMerchantId());
        if (Objects.isNull(merchant) || Objects.equals(merchant.getIsDel(), BooleanEnums.TRUE.getCode())) {
            throw new CrmebException("店铺信息异常");
        }

        // 原有推荐人推荐人数减一
        User oldSpreader = userManager.findByUserId(user.getSpreadUid());
        if (Objects.nonNull(oldSpreader)) {
            LambdaUpdateWrapper<User> oldSpreaderUpdateWrapper = new LambdaUpdateWrapper<>();
            oldSpreaderUpdateWrapper.set(User::getSpreadCount, oldSpreader.getSpreadCount() - 1);
            oldSpreaderUpdateWrapper.set(User::getUpdateTime, CrmebDateUtil.nowDateTime());
            oldSpreaderUpdateWrapper.eq(User::getId, oldSpreader.getId());
            userDao.update(null, oldSpreaderUpdateWrapper);
        }

        // 新推荐人推荐人数加一
        User newSpreader = userManager.findByUserId(user.getSpreadUid());
        if (Objects.nonNull(newSpreader)) {
            LambdaUpdateWrapper<User> newSpreaderUpdateWrapper = new LambdaUpdateWrapper<>();
            newSpreaderUpdateWrapper.set(User::getSpreadCount, newSpreader.getSpreadCount() - 1);
            newSpreaderUpdateWrapper.set(User::getUpdateTime, CrmebDateUtil.nowDateTime());
            newSpreaderUpdateWrapper.eq(User::getId, newSpreader.getId());
            userDao.update(null, newSpreaderUpdateWrapper);
        }

        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(User::getSpreadUid, merchant.getManagerUid());
        updateWrapper.set(User::getSpreadMerchantId, req.getNewMerchantId());
        updateWrapper.set(User::getUpdateTime, CrmebDateUtil.nowDateTime());
        updateWrapper.eq(User::getId, req.getUserId());
        userDao.update(null, updateWrapper);

    }

    @Override
    public String userRealName(Integer userId) {
        User user = userManager.findByUserId(userId);
        return Objects.nonNull(user) ? user.getRealName() : null;
    }

    @Override
    public String userPhone(Integer userId) {
        User user = userManager.findByUserId(userId);
        return Objects.nonNull(user) ? user.getPhone() : null;
    }

    @Override
    public String bankcardNumber(Integer userId) {
        LambdaQueryWrapper<UserBank> bankWrapper = new LambdaQueryWrapper<>();
        bankWrapper.eq(UserBank::getUserId, userId);
        bankWrapper.eq(UserBank::getDeleted, BooleanEnums.FALSE.getCode());
        UserBank userBank = userBankDao.selectOne(bankWrapper);
        if (Objects.nonNull(userBank)) {
            return userBank.getBankcardNumber();
        }
        return null;
    }
}
